/*********************************************************
          File Name:tt.cpp
          Author: Abby Cin
          Mail: abbytsing@gmail.com
          Created Time: Sun 13 Sep 2015 03:43:24 PM CST
**********************************************************/

#include <iostream>
using namespace std;

//-----------------------------
// better add the two lines, or some compiler will complain
// 最好在使用友元之前声明友元函数
class T;

T add(T &t1, T &T2);
//------------------------------

class T{
        friend T add(T &, T &);
        friend ostream &print(ostream &os, T &);
        private:
                int n;
                mutable int m;  // mutale member can be modified even in a `const` Object
        public:
                T() = default;
                T(int i): n(i), m(i) {}
                T(int i, int j): T(i+j) {}  // delegating constructor(委托构造) delegat `T(int i): n(i), m(i) {}` 
                //void modify()const { n = 10; } convert `*this` to `const *this` implicitly
                void modify() { n = 10; }
                void change() const { m = 10; cout << m << endl;};
                int get() { cout << n << endl; return this->n; }
};

T add(T &t1, T &t2)
{
        T tmp;
        tmp.n = t1.n + t2.n;
        return tmp;
}

ostream &print(ostream &os, T &t)
{
        os << "out = " << t.n << endl;
        return os;
}

// member is private in default
class Person {
        string name;
        string addr;

        public:
                Person() = default;
                Person(string n, string a): name(n), addr(a){}

                //string const &get_name() const { return name; }
                //string const &get_addr() const { return addr; }

                // same as above
                auto get_name() const -> string const & { return name; }
                auto get_addr() const -> string const & { return addr; }
};

int main()
{
        T x(3);
        x.modify();
        x.change();
        x.get();

        T y(3);

        T tmp = add(x,y);
        print(cout, tmp);

        Person p("abby", "US");
        cout << p.get_name() << endl;
        return 0;
}
